/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.allotmanagementpc.impl;

import com.lightkits.common.TransactionValidate;
import com.lightkits.common.db.entity.FndItemBase;
import com.lightkits.common.db.entity.FndOrganizationBase;
import com.lightkits.common.db.entity.FndWarehouse;
import com.lightkits.common.db.entity.WmExecuteLine;
import com.lightkits.common.db.entity.WmRequestHeader;
import com.lightkits.common.db.entity.WmRequestLine;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.common.db.entity.event.BdEventRecord;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.json.JsonUtil;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.wms.domain.allotmanagementpc.AllotManagementPcService;
import com.lightkits.wms.domain.allotmanagementpc.CreateDocumentEvetParamService;
import com.lightkits.wms.domain.allotmanagementpc.CreateDocumentParamsService;
import com.lightkits.wms.domain.arrivalnotice.repo.BdEventDBService;
import com.lightkits.wms.domain.arrivalnotice.repo.BdEventRecordDBService;
import com.lightkits.wms.domain.nontaskpickinglist.repo.WmRequestHeaderService;
import com.lightkits.wms.domain.nontaskpickinglist.repo.WmRequestLineService;
import com.lightkits.wms.domain.rawmatstorage.repo.WmExecuteLineService;
import com.lightkits.wms.domain.saleticket.CreateSaleEventService;
import com.lightkits.wms.dto.allotmanagementpc.model.ExecuteLinePcDto;
import com.lightkits.wms.dto.allotmanagementpc.model.RequestHeaderPcDto;
import com.lightkits.wms.dto.allotmanagementpc.model.RequestLinePcDto;
import com.lightkits.wms.dto.allotmanagementpc.model.RequestValueDto;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 魏静
 * @create 2019-07-22 17:35
 * @desc 调拨管理2.0处理
 **/
@Service
public class AllotManagementPcServiceImpl implements AllotManagementPcService {
    private final CreateDocumentParamsService paramsService;
    private final WmRequestHeaderService headerService;
    private final WmRequestLineService lineService;
    private final CreateDocumentEvetParamService docEventService;
    private final BdEventDBService eventDBService;
    private final BdEventRecordDBService eventRecordDBService;
    private final CreateSaleEventService saleEventService;
    private final WmExecuteLineService executeLineService;

    @Autowired
    public AllotManagementPcServiceImpl(CreateDocumentParamsService paramsService,
                                        WmRequestHeaderService headerService,
                                        WmRequestLineService lineService,
                                        CreateDocumentEvetParamService docEventService,
                                        BdEventDBService eventDBService,
                                        BdEventRecordDBService eventRecordDBService,
                                        CreateSaleEventService saleEventService,
                                        WmExecuteLineService executeLineService) {
        this.paramsService = paramsService;
        this.headerService = headerService;
        this.lineService = lineService;
        this.docEventService = docEventService;
        this.eventDBService = eventDBService;
        this.eventRecordDBService = eventRecordDBService;
        this.saleEventService = saleEventService;
        this.executeLineService = executeLineService;
    }

    /**
     * 领料单参数校验
     *
     * @param headerPcDto 领料单头参数
     * @param linePcDtos  领料单行参数
     * @return
     */
    @Override
    public IResult checkParams(RequestHeaderPcDto headerPcDto,
                               List<RequestLinePcDto> linePcDtos) {
        if (ObjectUtil.isEmpty(headerPcDto)) {
            return IResult.fail("The Request Header is empty");
        }
        return IResult.success();

    }

    /**
     * 参数校验
     *
     * @param exePcDtos 执行行参数
     * @param valueDtos 请求行参数
     * @return IResult
     */
    @Override
    public IResult checkExeParams(List<ExecuteLinePcDto> exePcDtos, List<RequestValueDto> valueDtos) {
        try {
            valueDtos.forEach(dto -> {
                TransactionValidate check = TransactionValidate.beginValidity(WmRequestLine.class);
                check.checkIdValidity(dto.getRequestLineId(), "ID");
            });
            exePcDtos.forEach(dto -> {
                TransactionValidate check = TransactionValidate.beginValidity(WmRequestHeader.class);
                check.checkIdValidity(dto.getRequestHeaderId(), "ID");

                check = TransactionValidate.beginValidity(WmRequestLine.class);
                check.checkIdValidity(dto.getRequestLineId(), "ID");

                check = TransactionValidate.beginValidity(FndItemBase.class);
                check.checkIdValidity(dto.getItemId(), "ID");

                check = TransactionValidate.beginValidity(FndWarehouse.class);
                check.checkIdValidity(dto.getFromWarehouseId(), "ID");

                check = TransactionValidate.beginValidity(FndWarehouse.class);
                check.checkIdValidity(dto.getToWarehouseId(), "ID");

            });
        } catch (LightKitsBizException e) {
            return e.result();
        }
        return IResult.success();
    }

    /**
     * 创建领料单
     *
     * @param headerPcDto      领料单头参数
     * @param linePcDtos       领料单行参数
     * @param splitRequestFlag 是否分批
     * @return IResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult allotManagementPc(RequestHeaderPcDto headerPcDto,
                                     List<RequestLinePcDto> linePcDtos,
                                     Boolean splitRequestFlag) {
        List<WmRequestHeader> headerList = new ArrayList<>();
        //创建领料单头
        WmRequestHeader header = paramsService.createRequestHeader(headerPcDto);
        headerList.add(header);
        WmRequestHeader headerCopy = new WmRequestHeader();
        //领料单分批
        if (splitRequestFlag) {
            BeanUtils.copyProperties(header, headerCopy);
            headerCopy.setRequestNum(header.getRequestNum() + "-1");
            header.setRequestNum(header.getRequestNum() + "-2");
            headerList.add(headerCopy);
        }
        if (!ObjectUtil.isNullOrEmpty(headerList)) {
            headerService.insertBatch(headerList);
        } else {
            throw new LightKitsBizException("The Request Header are Empty ");
        }
        //创建事件
        List<BdEvent> bdEventList = new ArrayList<>();
        BdEvent event = docEventService.createEvent(header, "WM_TRANSFAR_CREATE");
        bdEventList.add(event);
        BdEvent eventCopy = new BdEvent();
        if (splitRequestFlag) {
            BeanUtils.copyProperties(event, eventCopy);
            bdEventList.add(eventCopy);
        }
        if (!ObjectUtil.isNullOrEmpty(bdEventList)) {
            eventDBService.insertBatch(bdEventList);
        } else {
            throw new LightKitsBizException("The Bd Event are Empty ");
        }
        //创建领料单头快照
        List<BdEventRecord> eventRecordList = new ArrayList<>();
        BdEventRecord eventRecord = saleEventService.createEventRecord("WM_REQUEST_HEADER",
                "", event.getId(), header.getId(), "", JsonUtil.toString(header));

        eventRecordList.add(eventRecord);
        BdEventRecord record = new BdEventRecord();
        if (splitRequestFlag) {
            BeanUtils.copyProperties(eventRecord, record);
            record.setEventId(eventCopy.getId());
            record.setSnapshotRecord(JsonUtil.toString(headerCopy));
            eventRecordList.add(record);
        }
        //创建领料单行
        List<WmRequestLine> lineList;
        if (splitRequestFlag && ObjectUtil.isNullOrEmpty(linePcDtos)) {
            lineList = paramsService.createRequestLine(linePcDtos, header.getId(), headerCopy.getId());
        } else {
            lineList = paramsService.createRequestLine(linePcDtos, header.getId(), null);
        }
        if (!ObjectUtil.isNullOrEmpty(lineList)) {
            lineService.insertBatch(lineList);
        } else {
            throw new LightKitsBizException("The Request Lines are Empty ");
        }
        //创建领料单行快照
        lineList.forEach(target -> {
            BdEventRecord checkResult;
            FndItemBase base = new FndItemBase().selectById(target.getItemId());
            if (base.getTagControl()) {
                checkResult = saleEventService.createEventRecord(
                        "WM_REQUEST_LINE", "", event.getId(), target.getId(), "NEW",
                        JsonUtil.toString(target));
            } else {
                checkResult = saleEventService.createEventRecord(
                        "WM_REQUEST_LINE", "", eventCopy.getId(), target.getId(), "NEW",
                        JsonUtil.toString(target));
            }

            eventRecordList.add(checkResult);
        });
        if (!ObjectUtil.isNullOrEmpty(eventRecordList)) {
            eventRecordDBService.insertBatch(eventRecordList);
        } else {
            throw new LightKitsBizException("The BdEvent Records are Empty ");
        }

        return IResult.success();
    }

    /**
     * 执行表加值
     *
     * @param exeLineDtos      执行行参数
     * @param requestValueDtos 请求行参数
     * @return IResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult allotExecute(List<ExecuteLinePcDto> exeLineDtos, List<RequestValueDto> requestValueDtos) {
        WmRequestHeader header = new WmRequestHeader().selectById(exeLineDtos.get(0).getRequestHeaderId());
        //修改领料单头
        header.setProcessStatus("EXECUTED");
        headerService.updateById(header);
        //新增事件
        BdEvent event = docEventService.createEvent(header, "WM_TRANSFAR_EXECUTE");
        eventDBService.insert(event);

        //新增领料单头快照
        List<BdEventRecord> records = new ArrayList<>();
        BdEventRecord bdEventRecord = saleEventService.createEventRecord("WM_REQUEST_HEADER",
                "", event.getId(), header.getId(), "EXECUTED", JsonUtil.toString(header));
        records.add(bdEventRecord);
        //修改领料单行
        List<WmRequestLine> requestLines = new ArrayList<>();
        requestValueDtos.forEach(target -> {
            WmRequestLine line = new WmRequestLine().selectById(target.getRequestLineId());
            line.setConfirmedQty(new BigDecimal(target.getExecuteQty()));
            line.setExeutedQty(new BigDecimal(target.getExecuteQty()));
            line.setLineStatus("EXECUTED");
            requestLines.add(line);
        });
        lineService.insertBatch(requestLines);

        //创建领料单行快照
        requestLines.forEach(target -> {
            BdEventRecord record = saleEventService.createEventRecord("WM_REQUEST_LINE",
                    target.getExeutedQty().toString(), event.getId(), target.getId(),
                    "EXECUTED", JsonUtil.toString(target));
            records.add(record);
        });
        List<WmExecuteLine> executeLines = paramsService.createExeLine(exeLineDtos, event.getId());
        executeLineService.insertBatch(executeLines);
        executeLines.forEach(line -> {
            BdEventRecord record = saleEventService.createEventRecord("WM_EXECUTE_LINE",
                    line.getExecutedQty().toString(), event.getId(), line.getId(),
                    "EXECUTED", JsonUtil.toString(line));
            records.add(record);
        });
        eventRecordDBService.insertBatch(records);
        return IResult.success();

    }

    /**
     * 取消领料单状态
     *
     * @param cancelRequestHeaderId 取消领料单头
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelRequest(String cancelRequestHeaderId) {
        //获取领料单头
        WmRequestHeader header = new WmRequestHeader().selectById(cancelRequestHeaderId);
        header.setProcessStatus("CANCELLED");
        headerService.updateById(header);
        //创建事件
        BdEvent event = docEventService.createEvent(header, "REQUEST_TICKET_CANCELLED");
        eventDBService.insert(event);

        //创建快照
        BdEventRecord record = saleEventService.createEventRecord("WM_REQUEST_HEADER",
                "", event.getId(), header.getId(), "CANCELLED", JsonUtil.toString(header));
        eventRecordDBService.insert(record);

    }
}
